import requests
import os
import json
import re
from bs4 import BeautifulSoup
import time
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import execjs
from datetime import timedelta, datetime
import base64
import hashlib

# 缓存文件名
CACHE_KEY_NAME = '1.cookie'

# 防止抓包调试模式
FAKE_DEBUG = True

proxies = {
    'http': None,
    'https': None
} if FAKE_DEBUG else {}


# ZIP加密密钥
SAFE_ZIP_PROTECT = False
key = b'PLOCN35JKL0OEPQB'

def unix_time(dt):
    # 转换成时间数组
    timeArray = time.strptime(dt, "%Y-%m-%d %H:%M:%S")
    # 转换成时间戳
    timestamp = int(time.mktime(timeArray))
    return timestamp



class Client:

    def __init__(self, conn, getUA, logger,config):
        #配置信息
        self.config = config
        # 浏览器代理
        self.userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36'

        self.s = requests.session()
        self.s.trust_env = False
        self.s.headers = self._makeHeaders()

        self.verify = False

        # 最后一次访问的html内容
        self.html = ''
        self.refererUrl = ''

        # 是否登录
        self.isLogin = False

        # 当前登录的用户ID
        self.userId = ''
        
        self.money = 0

        self.apiProxy = None
        
        # 订单缓存
        self._orderCache = {}

        self.isPageInit = False

        self.conn = conn

        self.getUA = getUA

        self.logger = logger

    # 检查订单是否存在
    def checkIsExists(self, thirdOrderId):
        cursor = self.conn.cursor()
        cursor.execute('SELECT * FROM tbl_order WHERE third_order_id=%s', (thirdOrderId,))
        result = cursor.fetchone()
        cursor.close()
        
        if result == None:
            return False
        
        return True

    # 准备工作
    def instance(self):
        if os.path.exists(CACHE_KEY_NAME):
            with open(CACHE_KEY_NAME, 'r', encoding='utf-8') as f:
                localCookie = f.read()

            try:
                originData = json.loads(localCookie)
                for d in originData:
                    self.s.cookies.set(d['name'], d['value'], path=d['path'], domain=d['domain'])
            except Exception:
                os.remove(CACHE_KEY_NAME)

        self.openUrl('https://www.taobao.com/')
        self.heartBeat()

    def setUserAgent(self, userAgent):
        self.userAgent = userAgent
        self.s.headers = self._makeHeaders()

    def setApiProxy(self, apiProxy):
        self.apiProxy = apiProxy

    def _makeHeaders(self):
        return {
            'User-Agent': self.userAgent,
        }

    def openUrl(self, url):
        return self.s.get(url, verify=self.verify, proxies=proxies)

    def getCToken(self):
        self.ctoken = self.s.cookies.get('ctoken')
        return self.ctoken

    # 心跳包
    def heartBeat(self):
        self.conn.ping(reconnect=True)
        resp = self.getUserInfo()
        self.save()
        if resp == None:
            self.isLogin = False
            return

    # 获取当前登录帐号信息
    def getUserInfo(self):
        resp = self.s.get('https://mrchportalweb.alipay.com/interface/login/index/user', params={
            '_input_charset': 'utf-8',
            'ctoken': 'parent',
        }, headers={
            'sec-fetch-dest': 'empty',
            'sec-fetch-mode': 'cors',
            'sec-fetch-site': 'same-site',
            'referer': 'https://b.alipay.com/index2.htm',
            'x-requested-with': 'XMLHttpRequest'
        }, verify=self.verify, proxies=proxies)
        resp = resp.json()
        '''
        if 'stat' in resp and resp['stat'] == 'deny':
            self.apiProxy.reportAccountInfo({
                'login_status': 0,
                'money': self.money
            })
            return None
        '''
        #self.userId = resp['data']['userId']

        return resp

    # 打开登录页面
    def openLoginPage(self):
        self.getUA('login')
        resp = self.s.get('https://login.taobao.com/member/login.jhtml',headers={
            'sec-fetch-dest': 'document',
            'sec-fetch-mode': 'navigate',
            'sec-fetch-site': 'none',
            'upgrade-insecure-requests': '1'
        }, verify=self.verify, proxies=proxies)

        result = re.search(r'window.viewConfig =(.*?)};', resp.text)
        self.viewconfig = json.loads(result.group(0).replace('window.viewConfig =','').replace('};','}')) if result else None

        result = re.search(r'window.viewData =(.*?)};', resp.text)
        self.viewData = json.loads(result.group(0).replace('window.viewData =','').replace('};','}')) if result else None

        if self.viewconfig == None:
            raise Exception('rsaPublicKey参数为空')

        self.rsaPublicKey = self.viewconfig['rsaModulus']

        # 验证码地址 包含在viewconfig  api 节点中
        return resp



    # 生成密码
    def makeRSAPassword(self, password):

        if SAFE_ZIP_PROTECT:
            if not os.path.exists('rsa.js.zip'):
                raise FileNotFoundError('rsa.js.zip文件不存在')
            with open('rsa.js.zip', mode='rb') as f:
                zipBinData = f.read()

            dataLength = int.from_bytes(zipBinData[22:22+4], byteorder='big') >> 2

            # 检验数据包长度是否异常
            if dataLength != len(zipBinData):
                raise Exception('文件损坏')

            iv = bytes(reversed(zipBinData[26 : 26 + 8] + zipBinData[dataLength - 8 : dataLength]))

            ct_bytes = zipBinData[34 : dataLength - 8]
            cipher = AES.new(key, AES.MODE_CBC, iv)

            try:
                ct_bytes = unpad(cipher.decrypt(ct_bytes), AES.block_size)
                jsCode = ct_bytes.decode()
            except Exception:
                raise Exception('文件损坏')
        else:
            if not os.path.exists('rsa.js'):
                raise FileNotFoundError('rsa.js文件不存在')
            with open('rsa.js', mode='r', encoding='utf-8') as f:
                jsCode = f.read()

        ctx = execjs.compile(jsCode)
        rsaPassword = ctx.call('getPwd', password, self.rsaPublicKey)
        return rsaPassword

    # 登录
    def login(self, account, password, checkCode):
        formData = {
            'loginId': account,
            'password2': self.makeRSAPassword(password),
            'keepLogin': 'false',
            # 'ua': self.getUA('login'),
            'ua':'139#00704/As+ROqr1PC2Qksc6J4g2m60d0Vcv2QN+8oB0/F8gCt77bROKn4g2zC0FxpCc1aNA8WW0wh8GM6NsBWc1i4gpmC0D7TSt0+hnCx9B8Kfw41R9QzNP1Df9Sd2ezUZ/PVmDQy9iAt7uA3nWZ9uzZr1gPcUusX20xWHVSvFR7q00QoWCVNHGf6xs2dpqr8KXlgSJxrfu/48bBCQR7eiSPTmB4dUOKe84J/dGxNPUkFkOGufqQaElJaIPnFdq4QicNKWqxZPhS4P4aHdaS18KJK8Nzdpq26mRPBQboQkbQxF4f37uHBKGffHWHSSZZCKaQKi7xDfU4Qx4XV7uXJKrnanp7qp4SQibeAnBxMnNk4k4ZgGZVa6NoDl4nFp3pzg6WAUqfinaQQfjwqGqw56hwemFjslbf6k3xJXNSHvR7q00So7Volf3P00VSQVk8rr0dWIyNHvRsX07SWxVVzf3P00VSWVSsXPD007VSVv3PX0701Hke8PMs3gacmCmxvSD79iOhH78qOsfGdtLuFKV+E7HeS6XJk5NdQSOeUFRp2i2yo9Kgt28A9Ni+GccIMhHMS5/O1UqjJX/0CalMpq/4gmB71cMBKzgTRvU5Zd5Yy3qTZppsvcPVpiPHT2tFYXGuQs3/nax8TLvly+nHIX++APgMgwTvFS7vcgMt4t8twKjwxLeI9zihEzcDmxkGWVPORc6PN5Xa7iAzG84BXBmdvHH+DIZp4M6KUCw4pZRHgyZ03/fp3PQ5v1xLlmqyR0hwg3c6I/+p0nrf3/GDH+KF62V+DERvr5DCpixAuuMED36k5XnRn1BqI1pJGmbpxHNoBHxBMsSgijONNoJIG3yqh3gwhQ9UloHaQOoynKBOUH68GoPo9UebFGARuDdOD1pwC+7sri+0t+h1l2CDzORJ7EJWwsQqYnPYgJzswLbOH2XiDicOog/2kHu+k0DDdtShsPH9pHa46xBjaoE3r2ShS8pfHN2pxMH/OpMi1IwwfLamxuarSBx6zNG9sV4FGXBVNAkWssND00X42KEvGMuN1H1veapMFOySpnLJYLD5jaKdIV93nz32D9bAS5Nnj9Wdh',
            'umidGetStatusVal': '4',
            'screenPixel': '1536x864',
            'navlanguage': 'zh-CN',
            'navUserAgent': self.userAgent,
            'navPlatform': 'Win32',
            'sub': 'true',
            'appName': self.viewData['loginFormData']['appName'],
            'appEntrance': self.viewData['loginFormData']['appEntrance'],
            '_csrf_token': self.viewData['loginFormData']['_csrf_token'],
            'umidToken': self.viewData['loginFormData']['umidToken'],
            'hsiz': self.viewData['loginFormData']['hsiz'],
            'bizParams': self.viewData['loginFormData']['bizParams'],
            'style': self.viewData['loginFormData']['style'],
            'appkey': self.viewData['loginFormData']['appkey'],
            'from': self.viewData['loginFormData']['from'],
            'isMobile': self.viewData['loginFormData']['isMobile'],
            'lang': self.viewData['loginFormData']['lang'],
            'returnUrl': self.viewData['loginFormData']['returnUrl'],
            'fromSite': self.viewData['loginFormData']['fromSite'],
            'bx-ua': '139#00704ZjHSuaXb1t72Qksc6J4g2m60d0Vcv2QN 8oB0/F8gCt77bROKn4g2zC0FxpCc1aNA8WW0wh8GM6NsBWc1i4gpmC0D7TSt0 hnCx9B8Kfw41R9QzNP1Df9Sd2ezUZ/PVmDQy9iAt7uA3nWZ9uzZr1KychqwX20xWHVSvFR7q00QokLVNHGf6xstbbWVMKuUalKxsIU46x4uLiuHcih8jnlxCP7oRva5Z4y168aU48cGFWqDriryel3xFp6lZEaeTa3P6hl54nL8jNZlGKKQs8Npgpjp6EODqdXoMm6e4kFHaiDKQkNdJvrxjtZKekR1DlyoexdVRdZf3VZSN6bS4zs1uUZa6HZeY4d1ih6G4ILBjVqsDiKnKIFxu2LkKCL8wJGxj2hbHI6sLfqdDgvdZIl7j8vW4Cbiji9QMPrlePqQHJbJembgEWGSWVSsXPD0WHHSHvR7q00fW7SIwfj2XuSSWHG1qPDyc7kSHvR7q00So7Volf37W0ySoVV1qftP0PSSVG0RjYY2peJ8FW3ZVdKoWjfx hdkRwzXZYid3jKExyYkW1Y Dj3jMKfOV12fuHRV2uNXD4VEt1bSkKdopgnxpXhp9snklHwRnJ7 YexavCdnS0CsoUkkZFDx2yc24 1M/A9G3H/JoXqwaXG1sADOc9BQqx/ui0VsHOybDXVwdsR7ksDLJZpr6g2xyUS4xoe6RmEE7ns tjJXgUxYZJw3EHkleSnQgSuNQMSP9D8svLy9bP7Fjf3wWURUyZpCn/7bC6DNhm4UC6UGq/y iW4jsRa4hfBzB/Mr32/HJQuwuqaKbKXicx0NzzewjkVg 4v4f7AcS8ywGEBPpUatmSwDXrFUKJZa7JoBFyPntSn 8ZCPqFeLvqjaVYEy4wWU1 mhAfDhDDFwHvmCfNqggtswhhkdeM bdH/e5itUD8lCGwlErMbCVQnGIx MBzxwH7CnNu25aEcd1bsB2AV7kEhblHhh25ccfNCF /x86 vac3L pkSh0HLYe9L43Cn09OhGR4oMEZNPEi ULaKGoYpVDXj4C6QKXBUFCXpaCh0vktNxuYB bDECMW9xd1zXoXgDXrkYmpDpdOTDdlY8GeSoYUSFRtEGrNCoWTOnCCgnb0QS65l2x7C/AnhowypPfaRL5JfwltVJ2 Wb5FNVa P69UOJ 5CsZF9NeeBho6zoRuBM2bJmtiK/0pkceEV6YJARO3fV68KDiPBqVGuQepnMFSEmnaAoCBb6NlDnus7TFCGO5T43gLxLkwqt9j1rzFNL4Crhe/RFxmP/CcjP4pT5Ow2sAmLmdF0==',
            'bx-umidtoken': 'defaultToken4_init_failed with failed@@https://login.taobao.com/member/login.jhtml@@'+self.viewData['currentTime']
        }

        # 提交登录
        resp = self.s.post('https://login.taobao.com'+self.viewconfig['api']['loginApi'], data=formData, headers={
            'Origin': 'https://login.taobao.com',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Sec-Fetch-Site': 'same-site',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-User': '?1',
            'Sec-Fetch-Dest': 'empty',
            'Referer': 'https://login.taobao.com/member/login.jhtml?from=taobaoindex&f=top&style=&sub=true&redirect_url=https%3A%2F%2Fmyseller.taobao.com%2Fhome.htm',
        }, verify=self.verify, allow_redirects=False, proxies=proxies)

        if resp.status_code == 200:
            jsres = json.loads(resp.text)
            if jsres['hasError']==True :
                return False
            else:
                iframeRedirectUrl = jsres['content']['data']['iframeRedirectUrl']
                resp = self.s.get(iframeRedirectUrl,headers={
                # resp = self.s.get('https://myseller.taobao.com/home.htm',headers={
                    'Host': 'login.taobao.com',
                    'sec-fetch-dest': 'document',
                    'sec-fetch-mode': 'navigate',
                    'sec-fetch-site': 'same-origin',
                    'upgrade-insecure-requests': '1'
                }, verify=self.verify, proxies=proxies)
                print(resp.text)
                # 取出验证url,验证是否登录成功
                result = re.findall(r'<iframe(.*?)<\/iframe>', resp.text, re.S)
                checksrc = BeautifulSoup('<form' + result[0] + '</form>', "lxml").select_one('form').attrs['src']
                print(checksrc)
                resp = self.s.get(checksrc,headers={
                    'Host': 'passport.taobao.com',
                    'sec-fetch-dest': 'iframe',
                    'sec-fetch-mode': 'navigate',
                    'sec-fetch-site': 'same-site',
                    'upgrade-insecure-requests': '1',
                    'Referer':iframeRedirectUrl
                }, verify=self.verify, proxies=proxies)
                print(resp.url)
                # normal_validate 验证
                normal_validate_url = resp.url
                resp = self.s.get(normal_validate_url,headers={
                    'Host': 'passport.taobao.com',
                    'sec-fetch-dest': 'iframe',
                    'sec-fetch-mode': 'navigate',
                    'sec-fetch-site': 'same-site',
                    'upgrade-insecure-requests': '1',
                    'Referer':iframeRedirectUrl
                }, verify=self.verify, proxies=proxies)
                # verify_modes 验证
                verify_modes_url = re.search(r'window.location.href = (.*?)+window._iv_umidfg;', resp.text)[0].replace('window.location.href = "','').replace('"+window._iv_umidfg;','undefined')
                resp = self.s.get(verify_modes_url,headers={
                    'Host': 'passport.taobao.com',
                    'sec-fetch-dest': 'iframe',
                    'sec-fetch-mode': 'navigate',
                    'sec-fetch-site': 'same-origin',
                    'upgrade-insecure-requests': '1',
                    'Referer':normal_validate_url
                }, verify=self.verify, proxies=proxies)
                print(resp.url)
                if '经检测当前操作环境安全' in resp.text:
                    self.logger.info('登录成功')
                    self.logger.info('启动完毕, 正在监听中')
                    self.save()
                elif '手机验证码验证' in resp.text:
                    self.logger.info('检测到需要手机验证码')
                    return False
        return True


    def save(self):
        localCookie = []
        for a in self.s.cookies:
            localCookie.append({
                'name': a.name,
                'domain': a.domain,
                'path': a.path,
                'value': a.value,
            })
        
        if len(localCookie) == 0:
            return

        with open(CACHE_KEY_NAME, 'w', encoding='utf-8') as f:
            f.write(json.dumps(localCookie))

    def __del__(self):
        self.save()
